#include "controller.h"
#include <math.h>

Controller* Controller::m_controller = 0;

Controller::Controller()
:m_calcMagSetted(false)
{
	setCharacter(",");
}

Controller::~Controller()
{
}

Controller& Controller::instance()
{
 return m_controller ? *m_controller : *(m_controller = new Controller());
}

void
Controller::pushData( Data _initial )
{
 m_dataSheet.push_back( _initial );
}

vector<Data> Controller::getDataSheet()
{
 return m_dataSheet;
}

void
Controller::reset()
{
 m_dataSheet.clear();
}

void
Controller::sort(PROP _p)
{
 
  int i = m_dataSheet.size();

  if (i>1)
  {
    bool ordered = false;
    int k = i;

    while ( (ordered == false)&&(k > 1))
    {
      ordered = true;
      int j = -1;
      int l = 0;

      while (l<i-1)
      {
        j=j+1;
        Data sortFirstData = m_dataSheet[j];
        int year1 = sortFirstData.getyear();
        string date1 = sortFirstData.getdate();
        string hour1 = sortFirstData.gethour();
        double lat1 = sortFirstData.getlat();
        double lng1 = sortFirstData.getlong();
        int error1 = sortFirstData.geterror();
        string state1 = sortFirstData.getstate();
        double depth1 = sortFirstData.getdepth();
        double mag1 = sortFirstData.getmag();
        int type1 = sortFirstData.gettype();
        char cat1 = sortFirstData.getcat();
        string Io1 = sortFirstData.getIo();
        double area1 = sortFirstData.getarea();
        string local1 = sortFirstData.getlocal();
        string comment1 = sortFirstData.getcomment();
        double Mw11 = sortFirstData.getMw1();
        double Mw21 = sortFirstData.getMw2();
        double Mw31 = sortFirstData.getMw3();
        double Mw1f = sortFirstData.getMw();

        l=l+1;
        Data sortLastData = m_dataSheet[l];
        int year2 = sortLastData.getyear();
        string date2 = sortLastData.getdate();
        string hour2 = sortLastData.gethour();
        double lat2 = sortLastData.getlat();
        double lng2 = sortLastData.getlong();
        int error2 = sortLastData.geterror();
        string state2 = sortLastData.getstate();
        double depth2 = sortLastData.getdepth();
        double mag2 = sortLastData.getmag();
        int type2 = sortLastData.gettype();
        char cat2 = sortLastData.getcat();
        string Io2 = sortLastData.getIo();
        double area2 = sortLastData.getarea();
        string local2 = sortLastData.getlocal();
        string comment2 = sortLastData.getcomment();
        double Mw12 = sortLastData.getMw1();
        double Mw22 = sortLastData.getMw2();
        double Mw32 = sortLastData.getMw3();
        double Mw2f = sortLastData.getMw();

        bool check;
        switch (_p)
        {
        case eyear: 
         {
          check = year1>year2;
        	 break;
         }
        case edate: 
         {
          check = date1>date2;
        	 break;
         }
        case ehour: 
         {
          check = hour1>hour2;
        	 break;
         }
        case elat: 
         {
          check = lat1>lat2;
        	 break;
         }
        case elng: 
         {
          check = lng1>lng2;
        	 break;
         }
        case eerror: 
         {
          check = error1>error2;
        	 break;
         }
        case estate: 
         {
          check = state1>state2;
        	 break;
         }
        case edepth: 
         {
          check = depth1>depth2;
        	 break;
         }
        case emag: 
         {
          check = mag1>mag2;
        	 break;
         }
        case etype: 
         {
          check = type1>type2;
        	 break;
         }
        case ecat: 
         {
          check = cat1>cat2;
        	 break;
         }
        case eIo: 
         {
          check = Io1>Io2;
        	 break;
         }
        case earea: 
         {
          check = area1>area2;
        	 break;
         }
        case elocal: 
         {
          check = local1>local2;
        	 break;
         }
        case ecomment: 
         {
          check = comment1>comment2;
        	 break;
         }
        case eMw1: 
         {
          check = Mw11>Mw12;
        	 break;
         }
        case eMw2: 
         {
          check = Mw21>Mw22;
        	 break;
         }
        case eMw3: 
         {
          check = Mw31>Mw32;
        	 break;
         }
        case eMw: 
         {
          check = Mw1f>Mw2f;
        	 break;
         }
        }

        if (check)
        {

         Data data2(year2,date2,hour2,lat2,lng2,error2,state2,depth2,mag2,
          type2,cat2,Io2,area2,local2,comment2,Mw12,Mw22,Mw32,Mw2f);
         m_dataSheet[j] = data2;

         Data data1(year1,date1,hour1,lat1,lng1,error1,state1,depth1,mag1,
          type1,cat1,Io1,area1,local1,comment1,Mw11,Mw21,Mw31,Mw1f);
         m_dataSheet[l] = data1;

          ordered = false;

        }
        k = k+1;
      }
    }
  }
}

void
Controller::invert()
{
 int numData = m_dataSheet.size();
 vector<Data> newDataSheet;
 for (unsigned int i = 0; i<numData; ++i)
 {
  newDataSheet.push_back(m_dataSheet[numData-i-1]);
 }
 m_dataSheet = newDataSheet;
}

void
Controller::setCalcMag( double _a1, double _b1, double _c1, double _a2, double _b2, double _c2, double _w1, double _w2 )
{
 m_calcMagSetted = true;


 double mb, s, Mw1, Mw2, Mw3, Mwf;
 int t;
 for(std::vector<Data>::iterator it = m_dataSheet.begin(); it != m_dataSheet.end(); ++it)
 {

  Mw1 = 0;
  Mw2 = 0;
  Mw3 = 0;
  Mwf = 0;

  mb = it->getmag();
  s = it->getarea();
  t = it->gettype();

  s = s*1000;

  Mw1 = _a1*mb*mb + _b1*mb + _c1;

  if (s>0)
   Mw2 = _a2*log10(s) + _b2*sqrt(s) + _c2;      

  if (t == 0 || t == 1 || t == 2)
  {
   if (s<=0)
   {
    Mwf = Mw1;
    Mw2 = -10*t;
    Mw3 = -10*t;
   }
   else
   {
    Mw3 = Mw1*_w1 + Mw2*_w2;
    Mwf = Mw3;
   }
   if (t==0)
   {
    Mw2 = -10;
    Mw3 = -10;
   }
  }
  else if (t == 3)
  {
   Mwf = Mw2;
   Mw1 = -30;
   Mw3 = -30;
  }
  else if (t == 4 || t == 5)
  {
    Mwf = Mw1;
    Mw2 = -10*t;
    Mw3 = -10*t;   
  }
  else if (t == -1)
  {
   Mw1 = -100; 
   Mw2 = -100; 
   Mw3 = -100;
   Mwf = -100;
  }

  Data d(it->getyear(),it->getdate(), it->gethour(),    it->getlat(),
         it->getlong(),it->geterror(),it->getstate(),   it->getdepth(),
         it->getmag(), it->gettype(),   it->getcat(),   it->getIo(),
         it->getarea(),it->getlocal(),it->getcomment(), Mw1, Mw2, Mw3, Mwf);
  *it = d;
 }
 
}

void
Controller::setCalcMag(double _a1, double _b1, double _c1, double _a2, double _b2, double _c2, double _weightMb[], double _weightA[])
{

 double mb, s, Mw1, Mw2, Mw3, Mwf;
 int t;
 for(std::vector<Data>::iterator it = m_dataSheet.begin(); it != m_dataSheet.end(); ++it)
 {

  Mw1 = -10;
  Mw2 = -10;
  Mw3 = -10;
  Mwf = -10;

  mb = it->getmag();
  s = it->getarea();
  t = it->gettype();

  s = s*1000;

  Mw1 = _a1*mb*mb + _b1*mb + _c1;
  if (s>0)
  {
   Mw2 = _a2*log10(s) + _b2*sqrt(s) + _c2; 
   Mw3 = _weightMb[t]*Mw1 + _weightA[t]*Mw2;
   Mwf = Mw3;
  }
  else
  {
   Mwf = Mw1;
  }

  Data d(it->getyear(),it->getdate(), it->gethour(),    it->getlat(),
   it->getlong(),it->geterror(),it->getstate(),   it->getdepth(),
   it->getmag(), it->gettype(),   it->getcat(),   it->getIo(),
   it->getarea(),it->getlocal(),it->getcomment(), Mw1, Mw2, Mw3, Mwf);
  *it = d;
 }
}

void
Controller::setCalcMag(double _a1[], double _b1[], double _c1[], double _a2[], double _b2[], double _c2[], double _weightMb[], double _weightA[])
{

 double mb, s, Mw1, Mw2, Mw3, Mwf;
 int t;
 for(std::vector<Data>::iterator it = m_dataSheet.begin(); it != m_dataSheet.end(); ++it)
 {

  Mw1 = 0;
  Mw2 = 0;
  Mw3 = 0;
  Mwf = 0;

  mb = it->getmag();
  s = it->getarea();
  t = it->gettype();

  s = s*1000;

  Mw1 = _a1[t]*mb*mb + _b1[t]*mb + _c1[t];

  if (s>0)
   Mw2 = _a2[t]*log10(s) + _b2[t]*sqrt(s) + _c2[t];     

  Mwf = _weightMb[t]*Mw1 + _weightA[t]*Mw2;

  Data d(it->getyear(),it->getdate(), it->gethour(),    it->getlat(),
   it->getlong(),it->geterror(),it->getstate(),   it->getdepth(),
   it->getmag(), it->gettype(),   it->getcat(),   it->getIo(),
   it->getarea(),it->getlocal(),it->getcomment(), Mw1, Mw2, Mw3, Mwf);
  *it = d;
 }
}

bool Controller::calcMagSetted()
{
 return m_calcMagSetted;
}

std::string Controller::getCharacter()
{
	return m_csv;
}

void Controller::setCharacter( string txt )
{
	m_csv = txt;
}
